﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using System.Reflection;
using System.Linq.Expressions;

namespace KDSugar.Galaxy.API.Query
{
    /// <summary>
    /// 单据查询操作指令
    /// </summary>
    /// <typeparam name="T">
    /// 需要执行查询操作的数据模型
    /// </typeparam>
    public class QueryCommand<T> : Base.BaseCommand where T : class, new()
    {
        /// <summary>
        /// 单据查询操作指令URL
        /// </summary>
        public const string QUERY_COMMAND_URL = "/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery.common.kdsvc";

        /// <summary>
        /// 最大行数极限值
        /// </summary>
        public const int MAX_LIMIT = 2000;

        /// <summary>
        /// 单据查询操作指令初始化
        /// </summary>
        /// <param name="_client">API客户端</param>
        public QueryCommand(GalaxyCloudAPIClient _client)
            : base(QUERY_COMMAND_URL, null, _client)
        {
            Limit = MAX_LIMIT;
        }

        /// <summary>
        /// 验证查询返回数据是否符合规则
        /// </summary>
        /// <param name="_responseData"></param>
        /// <returns></returns>
        public override bool ValidateResponseDataRule(string _responseData)
        {
            //bool result = true;
            //try
            //{
            //    List<List<Base.Result.BaseReturnInfo>> dataList = 
            //        JsonConvert.DeserializeObject<List<List<Base.Result.BaseReturnInfo>>>(_responseData);
            //    result = false;
            //}
            //catch
            //{
            //    Console.WriteLine("【查询指令执行-注意】查询指令执行返回数据检验逻辑过程触发异常抛出，但这个系设计故意如此，无需担心");
            //    result = true;
            //}
            //return result;
            return true;
        }

        /// <summary>
        /// 业务对象表单Id
        /// </summary>
        public string FormId { get; set; }

        /// <summary>
        /// 执行查询数据操作
        /// </summary>
        /// <returns></returns>
        public List<T> ExecuteQueryBill()
        {
            FormId = null;
            List<T> result = null;
            Type type = typeof(T);
            if (type != null)
            {
                //string tableName = null;
                #region 获取单据模型类对象标识
                var tableTags = type.GetCustomAttributes(typeof(QueryTableTag), false);
                if (tableTags != null && tableTags.Count() > 0)
                    FormId = ((QueryTableTag)tableTags[0]).TableTagName;
                #endregion
                List<string> fields = new List<string>();
                List<PropertyInfo> pInfos = new List<PropertyInfo>();
                #region 获取单据模型字段标识
                var pList = type.GetProperties();
                if (pList != null)
                {
                    foreach (var p in pList)
                    {
                        if (p != null)
                        {
                            string tmpField = null;
                            var fieldTags = p.GetCustomAttributes(typeof(QueryFieldTag), false);
                            if (fieldTags != null && fieldTags.Count() > 0)
                                tmpField = ((QueryFieldTag)fieldTags[0]).FieldTagName;
                            if (!string.IsNullOrWhiteSpace(tmpField))
                            {
                                fields.Add(tmpField);
                                pInfos.Add(p);
                            }
                        }
                    }
                }
                #endregion
                SetFieldKeys(fields);
                var resultData = APIClient.ExecuteCommand(this);
                if (resultData != null && !string.IsNullOrWhiteSpace(resultData.ResponseData))
                {
                    string errorMsg = "未知错误";
                    try
                    {
                        if (ValidateResponseDataRule(resultData.ResponseData))
                        {
                            errorMsg = "返回数据JSON反序列化为对象失败";
                            List<List<object>> dataList = JsonConvert.DeserializeObject<List<List<object>>>(resultData.ResponseData);
                            if (dataList != null)
                            {
                                result = new List<T>();
                                int _row = 0;
                                foreach (List<object> _dataItem in dataList)
                                {
                                    _row++;
                                    T tData = (T)Activator.CreateInstance(typeof(T));
                                    for (int i = 0; i < _dataItem.Count; i++)
                                    {
                                        if (i < pInfos.Count)
                                        {
                                            try
                                            {
                                                pInfos[i].SetValue(tData, _dataItem[i], null);
                                            }
                                            catch
                                            {
                                                errorMsg = string.Format("第{2}行赋值出错|赋值字段【{0}】时出错，赋入的值为【{1}】",
                                                    pInfos[i].Name, _dataItem[i], _row);
                                                throw new Exception(errorMsg);
                                            }
                                        }
                                        else
                                        {
                                            break;
                                        }
                                    }
                                    result.Add(tData);
                                }
                            }
                            else
                            {
                                errorMsg = "反序列化对象后对象为NULL";
                                throw new Exception(errorMsg);
                            }
                        }
                        else
                        {
                            //throw new Exception(JsonConvert.SerializeObject(resultData));
                            errorMsg = "返回数据规则验证为false";
                            throw new Exception(errorMsg);
                        }
                    }
                    catch(Except.ExecuteException ex)
                    {
                        ex.OperateCommandName = GetOperateCommandName();
                        ex.AppendMessage = errorMsg;
                        ex.ExecuteData = resultData;
                        throw ex;
                    }
                }
                else
                {
                    throw new Exception(Constant.GetExecuteReturnNullErrorStr("查询"));
                }
            }
            else
            {
                throw new Exception("未获取到查询模型");
            }
            //FormId = null;
            return result;
        }

        /// <summary>
        /// 返回总行数
        /// </summary>
        public int TopRowCount
        {
            get
            {
                return _TopRowCount;
            }
            set
            {
                _TopRowCount = value < 0 ? 0 : value;
            }
        }

        private int _TopRowCount;

        /// <summary>
        /// 最大行数
        /// <para>默认为最大值2000</para>
        /// <para>如果赋值超过最大值2000将自动修正为2000</para>
        /// <para>如果赋值小于1则自动修正为1</para>
        /// </summary>
        public int Limit
        {
            get
            {
                return _Limit;
            }
            set
            {
                int tmpVal = value;
                if (tmpVal > MAX_LIMIT)
                    tmpVal = MAX_LIMIT;
                if (tmpVal < 1)
                    tmpVal = 1;
                _Limit = tmpVal;
            }
        }

        private int _Limit;

        /// <summary>
        /// 开始行索引
        /// </summary>
        public int StartRow
        {
            get
            {
                return _StartRow;
            }
            set
            {
                _StartRow = value < 0 ? 0 : value;
            }
        }

        private int _StartRow;

        /// <summary>
        /// 过滤条件
        /// </summary>
        public string FilterString { get; private set; }

        /// <summary>
        /// 直接设置过滤条件
        /// </summary>
        /// <param name="_filter">过滤条件字符串</param>
        public void SetFilter(string _filter)
        {
            FilterString = _filter;
        }

        /// <summary>
        /// 以Lambda表达式得形式设置过滤条件
        /// <para>注意：由于该功能实现并不是那么完善，所以表达式尽量简单，否则执行时容易报错</para>
        /// </summary>
        /// <param name="expression">Lambda表达式</param>
        /// <returns></returns>
        public void SetFilter(Expression<Func<T, bool>> expression)
        {
            if (expression != null)
            {
                Dictionary<string, string> dic = new Dictionary<string, string>();
                foreach(var para in expression.Parameters)
                {
                    if (para != null)
                    {
                        Type curType = para.Type;
                        string paraName = para.Name;
                        if (curType != null && !string.IsNullOrWhiteSpace(paraName))
                        {
                            foreach(var pInfo in curType.GetProperties())
                            {
                                if (pInfo != null)
                                {
                                    string tagFieldName = null;
                                    var attrs = pInfo.GetCustomAttributes(typeof(QueryFieldTag), false);
                                    if (attrs != null && attrs.Count() > 0)
                                        tagFieldName = ((QueryFieldTag)attrs[0]).FieldTagName;
                                    if (!string.IsNullOrWhiteSpace(tagFieldName))
                                        dic.Add(string.Format("{0}.{1}", paraName, pInfo.Name), tagFieldName);
                                }
                            }
                        }
                    }
                }
                var body = expression.Body;
                string expStr = body != null ? body.ToString() : null;
                if (!string.IsNullOrWhiteSpace(expStr))
                {
                    expStr = expStr.Replace("==", "=")
                            .Replace("!=", "<>")
                            .Replace(@"""", "'")
                            .Replace(Enum.GetName(typeof(ExpressionType), ExpressionType.AndAlso), "AND")
                            .Replace(Enum.GetName(typeof(ExpressionType), ExpressionType.OrElse), "OR")
                            .Replace(Enum.GetName(typeof(ExpressionType), ExpressionType.Not), "NOT ")
                            .Replace("= null", "IS NULL").Replace("= NULL", "IS NULL")
                            .Replace("<> null", "IS NOT NULL").Replace("<> NULL", "IS NOT NULL");
                    foreach(var kv in dic)
                    {
                        expStr = expStr.Replace(kv.Key, kv.Value);
                    }
                    #region IsNullOrWhiteSpace
                    while (expStr.Contains("IsNullOrWhiteSpace"))
                    {
                        string _p = expStr.Substring(expStr.IndexOf("IsNullOrWhiteSpace"));
                        if (!string.IsNullOrWhiteSpace(_p))
                        {
                            string _v = _p.Substring(_p.IndexOf('(') + 1, _p.IndexOf(')') - 1 - _p.IndexOf('('));
                            if (!string.IsNullOrWhiteSpace(_v))
                            {
                                expStr = expStr.Replace(string.Format("IsNullOrWhiteSpace({0})", _v),
                                    string.Format("{0} = '' OR {0} IS NULL OR REPLACE({0},' ','') = ''", _v));
                            }
                            else
                            {
                                break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    #endregion
                    #region IsNullOrEmpty
                    while (expStr.Contains("IsNullOrEmpty"))
                    {
                        string _p = expStr.Substring(expStr.IndexOf("IsNullOrEmpty"));
                        if (!string.IsNullOrWhiteSpace(_p))
                        {
                            string _v = _p.Substring(_p.IndexOf('(') + 1, _p.IndexOf(')') - 1 - _p.IndexOf('('));
                            if (!string.IsNullOrWhiteSpace(_v))
                            {
                                expStr = expStr.Replace(string.Format("IsNullOrEmpty({0})", _v),
                                    string.Format("{0} = '' OR {0} IS NULL", _v));
                            }
                            else
                            {
                                break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    #endregion
                }
                if (!string.IsNullOrWhiteSpace(expStr))
                    FilterString = expStr;
                //int a = 0;
            }
            //body.NodeType=ExpressionType.
        }

        /// <summary>
        /// 清除筛选条件
        /// </summary>
        public void CleanFilter()
        {
            FilterString = null;
        }

        /// <summary>
        /// 排序字段
        /// </summary>
        public string OrderString { get; private set; }

        /// <summary>
        /// 直接设置排序
        /// </summary>
        /// <param name="_order">排序字符串</param>
        public void SetOrderBy(string _order)
        {
            OrderString = _order;
        }

        /// <summary>
        /// 以Lambda形式新增排序
        /// </summary>
        /// <param name="expression">Lambda表达式</param>
        /// <param name="orderType">排序类型，默认正序</param>
        public void AppendOrderBy(Expression<Func<T,object>> expression,Constant.OrderTypeEnum orderType =Constant.OrderTypeEnum.Asc)
        {
            string orderStr = null;
            if (expression != null)
            {
                if (!string.IsNullOrWhiteSpace(OrderString))
                {
                    OrderString += ",";
                }
                else
                {
                    OrderString = "";
                }
                Dictionary<string, string> dic = new Dictionary<string, string>();
                foreach (var para in expression.Parameters)
                {
                    if (para != null)
                    {
                        Type curType = para.Type;
                        string paraName = para.Name;
                        if (curType != null && !string.IsNullOrWhiteSpace(paraName))
                        {
                            foreach (var pInfo in curType.GetProperties())
                            {
                                if (pInfo != null)
                                {
                                    string tagFieldName = null;
                                    var attrs = pInfo.GetCustomAttributes(typeof(QueryFieldTag), false);
                                    if (attrs != null && attrs.Count() > 0)
                                        tagFieldName = ((QueryFieldTag)attrs[0]).FieldTagName;
                                    if (!string.IsNullOrWhiteSpace(tagFieldName))
                                        dic.Add(string.Format("{0}.{1}", paraName, pInfo.Name), tagFieldName);
                                }
                            }
                        }
                    }
                }
                var body = expression.Body;
                orderStr = body != null ? body.ToString() : null;
                if (!string.IsNullOrWhiteSpace(orderStr))
                {
                    foreach (var kv in dic)
                    {
                        if (orderStr.Contains(kv.Key))
                        {
                            OrderString += kv.Value;
                            if (orderType == Constant.OrderTypeEnum.Desc)
                                OrderString += " DESC";
                            break;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 清除排序
        /// </summary>
        public void CleanOrderBy()
        {
            OrderString = null;
        }

        /// <summary>
        /// 需查询的字段key集合
        /// </summary>
        public string FieldKeys { get; private set; }

        /// <summary>
        /// 设置需要查询的字段key集合
        /// </summary>
        /// <param name="_fieldKeys">格式："key1,key2,..."</param>
        private void SetFieldKeys(string _fieldKeys)
        {
            FieldKeys = _fieldKeys;
        }

        /// <summary>
        /// 设置需要查询的字段key集合
        /// </summary>
        /// <param name="_fieldKeys"></param>
        private void SetFieldKeys(List<string> _fieldKeys)
        {
            //FieldKeys = null;
            //if (_fieldKeys != null)
            //{
            //    FieldKeys = "";
            //    foreach (string _field in _fieldKeys)
            //        FieldKeys += _field + ",";
            //    FieldKeys = FieldKeys.Substring(0, FieldKeys.Length - 1);
            //}
            FieldKeys = Helper.ArraysToString(_fieldKeys);
        }
    }
}
